import streamlit as st
import json
import time
import re
from typing import Dict, List, Any, Optional, Union, Tuple
from functools import lru_cache
from openai import OpenAI

client = OpenAI(
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    api_key="sk-8569c070be3b49f4a8c01d3a88d1989b",
)

# OpenAI配置
class OpenAIConfig:
    DEFAULT_MODEL = "qwen-turbo"
    DEFAULT_TEMPERATURE = 0.7
    API_TIMEOUT = 30


# 配置OpenAI API
@st.cache_data(ttl=3600, show_spinner=False)
def get_completion(prompt: str, model: str = OpenAIConfig.DEFAULT_MODEL) -> str:
    """调用OpenAI API获取响应，使用缓存提高性能

    Args:
        prompt: 提示词
        model: 使用的模型名称

    Returns:
        模型的文本响应
    """
    try:
        messages = [{"role": "user", "content": prompt}]
        response = client.chat.completions.create(
            model=model,
            messages=messages,
        )
        return  response.choices[0].message.content
    except Exception as e:
        st.error(f"API调用失败: {str(e)}")
        return ""



def clean_json_text(text: str) -> str:
    # 去除 markdown 代码块标记 ```json ```等
    text = re.sub(r"```(?:json)?", "", text).strip("` \n")
    # 替换非法反斜杠（如 \这、\新）
    text = re.sub(r'\\(?![nrt"\\/bfu])', '', text)
    return text

def parse_json_response(response: str) -> Dict[str, Any]:
    if not response:
        return {"error": "API返回内容为空"}
    try:
        return json.loads(response)
    except json.JSONDecodeError:
        try:
            cleaned = clean_json_text(response)
            print("=== Cleaned JSON ===", cleaned)
            return json.loads(cleaned)
        except Exception as e:
            return {
                "error": f"无法解析API响应: {str(e)}",
                "titles": ["解析错误 - 请检查格式或换一组内容"],
                "outline": "API返回了非JSON格式",
                "value_props": []
            }



# 第一阶段：创意构思
def ideation_stage(topic_area: str, target_audience: str, content_type: str) -> Dict[str, Any]:
    """内容创意构思阶段

    Args:
        topic_area: 主题领域
        target_audience: 目标受众
        content_type: 内容类型

    Returns:
        创意构思结果，包含标题选项、内容大纲和价值主张
    """
    prompt = f"""
    作为内容创意专家，请根据以下信息生成内容创意:

    主题领域: {topic_area}
    目标受众: {target_audience}
    内容类型: {content_type}

    请提供:
    1. 3个引人注目的标题选项
    2. 一个详细的内容大纲，包含引言、主要部分和结论
    3. 关键的吸引点和价值主张

    以JSON格式返回结果，格式如下:
    {{
        "titles": ["标题1", "标题2", "标题3"],
        "outline": "详细大纲...",
        "value_props": ["价值主张1", "价值主张2", ...]
    }}
    """

    response = get_completion(prompt)
    return parse_json_response(response)


# 第二阶段：专家评审
def expert_review_stage(ideation_result: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
    """多专家视角评审内容创意

    Args:
        ideation_result: 第一阶段的创意构思结果

    Returns:
        各专家的评审结果
    """
    roles = [
        {"name": "内容营销专家", "focus": "受众吸引力和市场定位"},
        {"name": "SEO专家", "focus": "搜索引擎优化和关键词策略"},
        {"name": "用户体验专家", "focus": "内容结构和可读性"}
    ]

    reviews = {}

    for role in roles:
        prompt = f"""
        你是一位{role['name']}，专注于{role['focus']}。

        请评审以下内容创意:
        {json.dumps(ideation_result, indent=2, ensure_ascii=False)}

        提供:
        1. 总体评分(1-10)
        2. 3个具体优点
        3. 2个改进建议
        4. 一个创新想法

        以JSON格式返回评审结果，格式如下:
        {{
            "rating": 评分,
            "strengths": ["优点1", "优点2", "优点3"],
            "improvements": ["建议1", "建议2"],
            "innovation": "创新想法"
        }}
        """

        response = get_completion(prompt)
        result = parse_json_response(response)

        if "error" in result:
            reviews[role["name"]] = {
                "rating": 0,
                "strengths": ["API返回错误"],
                "improvements": ["请重试"],
                "innovation": "无法获取创新想法"
            }
        else:
            reviews[role["name"]] = result

    return reviews


# 第三阶段：内容生成
def content_generation_stage(
        ideation_result: Dict[str, Any],
        expert_reviews: Dict[str, Dict[str, Any]],
        selected_title: str
) -> str:
    """根据创意和评审生成完整内容

    Args:
        ideation_result: 创意构思结果
        expert_reviews: 专家评审意见
        selected_title: 用户选择的标题

    Returns:
        生成的完整内容(Markdown格式)
    """
    # 提取关键评审意见，减少提示词长度
    condensed_reviews = {}
    for role, review in expert_reviews.items():
        condensed_reviews[role] = {
            "improvements": review.get("improvements", []),
            "innovation": review.get("innovation", "")
        }

    prompt = f"""
    作为专业内容创作者，根据以下信息创作完整内容:

    选定标题: {selected_title}

    内容大纲:
    {ideation_result.get('outline', '未提供大纲')}

    专家评审意见:
    {json.dumps(condensed_reviews, indent=2, ensure_ascii=False)}

    请创作一篇完整、引人入胜且结构清晰的内容。
    内容应该整合专家的改进建议，并保持专业性和吸引力。
    使用markdown格式，确保添加适当的标题层级、列表和强调。
    """

    return get_completion(prompt)


# 第四阶段：质量优化
def quality_enhancement_stage(generated_content: str) -> str:
    """优化生成的内容质量

    Args:
        generated_content: 生成的初始内容

    Returns:
        优化后的内容(Markdown格式)
    """
    prompt = f"""
    作为内容编辑，请优化以下内容:

    {generated_content}

    请:
    1. 检查并修正任何语法或拼写错误
    2. 提高表达的清晰度和简洁性
    3. 确保标题和小标题吸引人
    4. 优化段落和句子结构以提高可读性
    5. 增强整体的专业性和说服力

    返回优化后的完整内容（使用markdown格式）。
    不要对内容进行重写，只做必要的优化。
    """

    return get_completion(prompt)

#
# # 主界面
# def main():
# 设置页面配置
st.set_page_config(
    page_title="AI内容创作助手",
    page_icon="✍️",
    layout="wide",
    initial_sidebar_state="expanded"
)

# 应用样式
st.markdown("""
<style>
.main .block-container {
    padding-top: 2rem;
    padding-bottom: 2rem;
}
.stTabs [data-baseweb="tab-list"] {
    gap: 2px;
}
.stTabs [data-baseweb="tab"] {
    padding: 10px 16px;
    font-size: 16px;
}
.success-msg {
    padding: 10px;
    border-radius: 5px;
    background-color: #d4edda;
    border: 1px solid #c3e6cb;
    color: #155724;
    margin: 10px 0;
}
</style>
""", unsafe_allow_html=True)

# 页面标题
st.title("AI内容创作助手：多阶段智能流程")
st.caption("作者：何双新 ｜ COT：多阶段智能流程")

st.markdown("### 将复杂的内容创作过程分解为可管理的链式任务")

# 侧边栏 - API设置与系统信息
st.sidebar.header("⚙️ 设置")
api_key = 'sk-8569c070be3b49f4a8c01d3a88d1989b'
model_choice = 'qwen-turbo'
# 显示系统信息
st.sidebar.markdown("---")
st.sidebar.subheader("🔍 系统说明")
st.sidebar.markdown("""
**内容创作流程:**
1. 创意构思 - 生成内容构思
2. 专家评审 - 多角色评估反馈
3. 内容生成 - 完整内容创作
4. 质量优化 - 编辑润色完善

**提示:** 在每个步骤完成后才能进行下一步
""")

# 设置API密钥
if api_key:
    api_key = api_key

# 主界面 - 分阶段标签页
tab1, tab2, tab3, tab4 = st.tabs([
    "📝 创意构思",
    "🔍 专家评审",
    "📄 内容生成",
    "✨ 质量优化"
])

# 初始化会话状态
for key in ["ideation_result", "expert_reviews", "generated_content", "enhanced_content"]:
    if key not in st.session_state:
        st.session_state[key] = None

# 记录当前状态
if "current_stage" not in st.session_state:
    st.session_state.current_stage = 1

# 阶段1: 创意构思
with tab1:
    st.header("第一阶段：创意构思")
    st.markdown("在这个阶段，我们将根据您的需求生成内容创意、大纲和价值主张。")

    col1, col2 = st.columns(2)
    with col1:
        topic_area = st.text_input(
            "主题领域",
            placeholder="例如：人工智能、健康饮食、投资策略",
            help="您想要创作内容的主题范围"
        )
        target_audience = st.text_input(
            "目标受众",
            placeholder="例如：初创企业创始人、健身爱好者、新手投资者",
            help="您希望内容面向的读者群体"
        )

    with col2:
        content_type = st.selectbox(
            "内容类型",
            [
                "博客文章",
                "社交媒体帖子",
                "新闻稿",
                "教程",
                "电子书章节",
                "播客脚本",
                "产品介绍",
                "市场分析报告",
                "项目总结报告",
                "行业趋势报告",
                "技术白皮书",
                "公司内部培训资料",
                "工伤报告",  # 新增：适用于人事/行政
                "事故调查报告",  # 适用于安全部门
                "会议纪要",  # 日常办公文档
                "月度/季度汇报",  # 管理/团队协作
                "绩效评估报告"  # HR/管理层使用
            ],
            help="您想要创作的内容形式"
        )

    # 是否有必填字段为空
    has_empty_fields = not topic_area or not target_audience

    if st.button(
            "生成创意构思",
            key="ideation_btn",
            disabled=not api_key or has_empty_fields,
            help="点击开始生成内容创意"
    ):
        if not api_key:
            st.error("请先在侧边栏设置OpenAI API Key")
        elif has_empty_fields:
            st.warning("请填写所有必要字段")
        else:
            with st.spinner("🧠 正在生成创意..."):
                st.session_state.ideation_result = ideation_stage(
                    topic_area,
                    target_audience,
                    content_type
                )
                if "error" in st.session_state.ideation_result:
                    st.error(f"创意生成失败: {st.session_state.ideation_result['error']}")
                else:
                    st.session_state.current_stage = 2

    if st.session_state.ideation_result and "error" not in st.session_state.ideation_result:
        st.subheader("📋 创意结果")

        titles = st.session_state.ideation_result.get("titles", [])
        if titles:
            st.markdown("**🏷️ 推荐标题选项:**")
            for i, title in enumerate(titles):
                st.markdown(f"**{i + 1}.** {title}")

        outline = st.session_state.ideation_result.get("outline", "")
        if outline:
            st.markdown("**📑 内容大纲:**")
            st.markdown(outline)

        value_props = st.session_state.ideation_result.get("value_props", [])
        if value_props:
            st.markdown("**💎 价值主张:**")
            for prop in value_props:
                st.markdown(f"- {prop}")

        st.success("✅ 创意构思完成！请继续到「专家评审」阶段")
        if st.session_state.current_stage == 2:
            st.markdown("👉 **提示:** 请点击上方的「专家评审」标签继续")

# 阶段2: 专家评审
with tab2:
    st.header("第二阶段：专家评审")
    st.markdown("在这个阶段，多位专家将对内容创意进行评审，提供专业反馈。")

    if not st.session_state.ideation_result or "error" in st.session_state.ideation_result:
        st.info("⚠️ 请先完成创意构思阶段")
    else:
        if st.button(
                "获取专家评审意见",
                key="review_btn",
                help="点击获取多位专家的评审意见"
        ):
            with st.spinner("👀 专家正在评审中..."):
                st.session_state.expert_reviews = expert_review_stage(
                    st.session_state.ideation_result
                )
                st.session_state.current_stage = 3

        if st.session_state.expert_reviews:
            st.subheader("🔎 专家评审结果")

            for role, review in st.session_state.expert_reviews.items():
                rating = review.get('rating', 'N/A')
                rating_display = f"{rating}/10" if isinstance(rating, (int, float)) else rating

                with st.expander(f"📊 {role} 评审 (评分: {rating_display})"):
                    st.markdown("**优点:**")
                    for strength in review.get("strengths", []):
                        st.markdown(f"✅ {strength}")

                    st.markdown("**改进建议:**")
                    for improvement in review.get("improvements", []):
                        st.markdown(f"🔄 {improvement}")

                    st.markdown("**创新想法:**")
                    st.markdown(f"💡 {review.get('innovation', 'N/A')}")

            st.success("✅ 专家评审完成！请继续到「内容生成」阶段")
            if st.session_state.current_stage == 3:
                st.markdown("👉 **提示:** 请点击上方的「内容生成」标签继续")

# 阶段3: 内容生成
with tab3:
    st.header("第三阶段：内容生成")
    st.markdown("在这个阶段，我们将根据创意和专家评审意见生成完整内容。")

    if not st.session_state.expert_reviews:
        st.info("⚠️ 请先完成专家评审阶段")
    else:
        selected_title = st.selectbox(
            "选择要使用的标题",
            st.session_state.ideation_result.get("titles", ["无标题选项"]),
            help="从创意阶段生成的标题中选择一个用于最终内容"
        )

        if st.button(
                "生成完整内容",
                key="generate_btn",
                help="点击开始生成完整内容"
        ):
            with st.spinner("📝 正在生成内容...这可能需要一些时间"):
                st.session_state.generated_content = content_generation_stage(
                    st.session_state.ideation_result,
                    st.session_state.expert_reviews,
                    selected_title
                )
                st.session_state.current_stage = 4

        if st.session_state.generated_content:
            st.subheader("📄 生成的内容")

            # 显示内容预览部分
            content_preview = st.session_state.generated_content
            if len(content_preview) > 1000:
                # 只显示前1000个字符作为预览
                st.markdown(content_preview[:1000] + "...**[内容过长，仅显示部分预览]**")

                # 提供完整查看选项
                with st.expander("查看完整内容"):
                    st.markdown(content_preview)
            else:
                st.markdown(content_preview)

            st.success("✅ 内容生成完成！请继续到「质量优化」阶段")
            if st.session_state.current_stage == 4:
                st.markdown("👉 **提示:** 请点击上方的「质量优化」标签继续")

# 阶段4: 质量优化
with tab4:
    st.header("第四阶段：质量优化")
    st.markdown("在这个阶段，我们将优化内容的质量，修正错误并提升可读性。")

    if not st.session_state.generated_content:
        st.info("⚠️ 请先完成内容生成阶段")
    else:
        if st.button(
                "优化内容质量",
                key="enhance_btn",
                help="点击开始优化内容质量"
        ):
            with st.spinner("✨ 正在优化内容质量..."):
                st.session_state.enhanced_content = quality_enhancement_stage(
                    st.session_state.generated_content
                )

        if st.session_state.enhanced_content:
            # 创建标签页显示优化前后对比
            before_tab, after_tab = st.tabs(["优化前", "优化后"])

            with before_tab:
                st.markdown(st.session_state.generated_content)

            with after_tab:
                st.markdown(st.session_state.enhanced_content)

            # 提供下载功能
            st.download_button(
                label="📥 下载最终内容(Markdown)",
                data=st.session_state.enhanced_content,
                file_name=f"ai_content_{int(time.time())}.md",
                mime="text/markdown",
                help="下载优化后的完整内容为Markdown文件"
            )

            # 复制到剪贴板按钮（需要JavaScript）
            st.markdown("""
            <div class="success-msg">
                <h3>🎉 恭喜！完整内容创作流程已完成</h3>
                <p>您现在可以下载生成的内容或进行新的创作。</p>
            </div>
            """, unsafe_allow_html=True)

            # 提供重新开始选项
            if st.button("🔄 开始新的创作", help="清除当前状态并开始新的创作流程"):
                # 重置会话状态
                for key in ["ideation_result", "expert_reviews", "generated_content", "enhanced_content"]:
                    st.session_state[key] = None
                st.session_state.current_stage = 1
                st.rerun()
